package crond

import (
	"context"
	"sale-admin/config/mysql"
	"sale-admin/internal/app/grpc/client"
	"sale-admin/internal/app/grpc/protoc/devicec"
	"sale-admin/internal/dao"
	"strconv"

	"github.com/golang-module/carbon/v2"
)

type RobotInfo struct {
	MerchantID  string `json:"merchant_id"`
	RobotName   string `json:"robot_name"`
	SalesID     string `json:"sales_id"`
	LocationID  string `json:"location_id"`
	OpeningFlag string `json:"opening_flag"`
	OpeningTime string `json:"opening_time"`
	ProvinceID  string `json:"province_id"`
	CityID      string `json:"city_id"`
	DistrictID  string `json:"district_id"`
}

// 每天定时写入当日的机器运营数据空值
func SaveRobotDailyReport() (err error) {
	ctx := context.Background()
	db := mysql.NewDB()
	date := carbon.Now().ToDateString()
	// 查询所有机器
	var RobotInfoMap = make(map[string]RobotInfo)
	RobotList, robotCount, _ := dao.Robot{}.RobotList(ctx, db, "", date, "", "", "", "", "", "")
	if robotCount == 0 {
		return
	}
	for _, Robot := range RobotList {
		RobotInfoMap[Robot.RobotName] = RobotInfo{
			MerchantID:  Robot.MerchantID,
			RobotName:   Robot.RobotName,
			SalesID:     Robot.SalesID,
			LocationID:  strconv.Itoa(Robot.Areas3),
			OpeningFlag: Robot.OpeningFlag,
			OpeningTime: Robot.OpeningTime,
			ProvinceID:  strconv.Itoa(Robot.Areas1),
			CityID:      strconv.Itoa(Robot.Areas2),
			DistrictID:  strconv.Itoa(Robot.Areas5),
		}
	}

	for _, v := range RobotInfoMap {
		dao.RobotDailyReport{}.Save(ctx, db, v.MerchantID, v.RobotName, date,
			v.ProvinceID, v.CityID, v.DistrictID, v.LocationID,
			// 新城新店
			dao.RobotDailyReport{}.WithOpeningFlag(v.OpeningFlag),
			dao.RobotDailyReport{}.WithOpeningTime(v.OpeningTime),
		)
	}
	return
}

// 每天更新写入昨日的机器运营数据【库存、运行时长等数据】
func SaveYesterdayRobotDailyReport() (err error) {
	ctx := context.Background()
	db := mysql.NewDB()
	date := carbon.Yesterday().ToDateString()
	dateStart := carbon.Yesterday().StartOfDay().ToDateTimeString()
	dateEnd := carbon.Yesterday().EndOfDay().ToDateTimeString()
	// 查询所有机器
	var RobotInfoMap = make(map[string]RobotInfo)
	RobotList, robotCount, _ := dao.Robot{}.RobotList(ctx, db, "", date, "", "", "", "", "", "")
	if robotCount == 0 {
		return
	}
	for _, Robot := range RobotList {
		RobotInfoMap[Robot.RobotName] = RobotInfo{
			MerchantID:  Robot.MerchantID,
			RobotName:   Robot.RobotName,
			SalesID:     Robot.SalesID,
			LocationID:  strconv.Itoa(Robot.Areas3),
			OpeningFlag: Robot.OpeningFlag,
			OpeningTime: Robot.OpeningTime,
			ProvinceID:  strconv.Itoa(Robot.Areas1),
			CityID:      strconv.Itoa(Robot.Areas2),
			DistrictID:  strconv.Itoa(Robot.Areas5),
		}
	}
	// 记录库存信息
	SalesInfoList, _ := dao.RobotSalesInfo{}.GetRobotInventoryList(ctx, db, date)
	SalesInfoListMap := make(map[string]SalesIDSalesInfoList)
	for _, v := range SalesInfoList {
		SalesInfoListMap[v.RobotName] = SalesIDSalesInfoList{
			TotalGoodsInventory:    int64(v.GoodsInventory),
			TotalGoodsMaxInventory: int64(v.GoodsMaxInventory),
		}
	}

	// 记录运行时长 获取机器运营数据
	deviceAdminClient, err := client.GetDeviceAdminClient()
	RobotTaskMap := make(map[string]TaskStruct)
	if err == nil {
		for _, v := range RobotInfoMap {
			var req devicec.DeviceTaskInfoReq
			req.IdentificationCode = v.SalesID
			res, resErr := deviceAdminClient.DeviceTaskInfo(context.Background(), &req)
			if resErr == nil && res.Code != -1 {
				var TotalFaultDuration int64
				if res.TaskInfo.TotalTaskOdometer != -1 && res.TaskInfo.TotalTaskDuration != -1 {
					// 异常时长=24小时-出门时长-任务时长-回充时长-充电时长-待机时长
					TotalFaultDuration = 24*3600 -
						res.TaskInfo.TotalToTaskDuration/1000 -
						res.TaskInfo.TotalTaskDuration/1000 -
						res.TaskInfo.TotalToChargingDuration/1000 -
						res.TaskInfo.TotalChargingDuration -
						res.TaskInfo.TotalIdleDuration
				}
				// 86400 - 0 - (-1/1000) - 0 - 86400 - 86320
				RobotTaskMap[v.RobotName] = TaskStruct{
					TotalTaskOdometer:       res.TaskInfo.TotalTaskOdometer,
					TotalTaskDuration:       res.TaskInfo.TotalTaskDuration,
					TotalTaskRunCount:       res.TaskInfo.TotalTaskRunCount,
					TotalChargingDuration:   res.TaskInfo.TotalChargingDuration,
					TotalIdleDuration:       res.TaskInfo.TotalIdleDuration,
					TotalToTaskDuration:     res.TaskInfo.TotalToTaskDuration,
					TotalToChargingDuration: res.TaskInfo.TotalToChargingDuration,
					TotalFaultDuration:      TotalFaultDuration,
				}
			}
		}
	}
	// 运营事件
	EventList, _ := dao.Event{}.GetEventList(ctx, db, dateStart, dateEnd)
	EventMap := make(map[string]dao.SalesIDEventList)
	for _, v := range EventList {
		EventMap[v.RobotName] = v
	}
	// 写入数据库
	for _, v := range RobotInfoMap {
		opt := []dao.RobotDailyReportOption{}
		// 商品库存
		if _, ok := SalesInfoListMap[v.RobotName]; ok {
			opt = append(opt, dao.RobotDailyReport{}.WithGoodsInventory(SalesInfoListMap[v.RobotName].TotalGoodsInventory))
			opt = append(opt, dao.RobotDailyReport{}.WithGoodsMaxInventory(SalesInfoListMap[v.RobotName].TotalGoodsInventory))
		}
		// 运行时长
		if _, ok := RobotTaskMap[v.RobotName]; ok {
			opt = append(opt, dao.RobotDailyReport{}.WithTotalTaskOdometer(RobotTaskMap[v.RobotName].TotalTaskOdometer))
			opt = append(opt, dao.RobotDailyReport{}.WithTotalTaskDuration(RobotTaskMap[v.RobotName].TotalTaskDuration))
			opt = append(opt, dao.RobotDailyReport{}.WithTotalTaskRunCount(RobotTaskMap[v.RobotName].TotalTaskRunCount))
			opt = append(opt, dao.RobotDailyReport{}.WithTotalChargingDuration(RobotTaskMap[v.RobotName].TotalChargingDuration))
			opt = append(opt, dao.RobotDailyReport{}.WithTotalIdleDuration(RobotTaskMap[v.RobotName].TotalIdleDuration))
			opt = append(opt, dao.RobotDailyReport{}.WithTotalToTaskDuration(RobotTaskMap[v.RobotName].TotalToTaskDuration))
			opt = append(opt, dao.RobotDailyReport{}.WithTotalToChargingDuration(RobotTaskMap[v.RobotName].TotalToChargingDuration))
			opt = append(opt, dao.RobotDailyReport{}.WithTotalFaultDuration(RobotTaskMap[v.RobotName].TotalFaultDuration))
			operationDuration := RobotTaskMap[v.RobotName].TotalTaskDuration
			if _, ok := EventMap[v.RobotName]; ok {
				operationDuration = RobotTaskMap[v.RobotName].TotalTaskDuration - int64(EventMap[v.RobotName].AffectedTimeMill)
				if operationDuration < 0 {
					operationDuration = 0
				}
			}
			opt = append(opt, dao.RobotDailyReport{}.WithTotalOperationDuration(operationDuration))
		}
		dao.RobotDailyReport{}.Save(ctx, db, v.MerchantID, v.RobotName, date,
			v.ProvinceID, v.CityID, v.DistrictID, v.LocationID,
			opt...,
		)
	}
	return
}
